//#include "stdafx.h"
//#include <thread>         // std::thread
#include "stdio.h"
#include "conio.h"
//#include "Socket.h"
#include <winsock.h>

#define USE_MY_CODE

#define USE_MULTI_CLIENT

SOCKET	listenSocket;
//////////////////////////////////////////////////////////////
#ifdef USE_MULTI_CLIENT

const int nMaxClients = 3;

int nClientCounter = 0;
SOCKET clients[nMaxClients];

void threadFunc()
{
	while(nClientCounter < nMaxClients)
	{
		printf("aaa");
		clients[nClientCounter] = accept(listenSocket, NULL, NULL);
		if(clients[nClientCounter] == INVALID_SOCKET)
		{
			printf("\nClient %d CAN'T accepted!", nClientCounter);
			closesocket(clients[nClientCounter]);
			//return;
		}
		else
		{
			printf("\nClient %d accepted!", nClientCounter);
			nClientCounter++;
		}
	}
}

void removeSocket(int k)
{
	if(k < 0)
		return;
	if(k > nClientCounter - 1)
		return;
	closesocket(clients[k]);
	for(int i=k; i<nClientCounter; i++)
	{
		clients[i] = clients[i+1];
	}
	nClientCounter--;
}
#endif
void StreamServer(short nPort);
int Caculate(char* s);
void main(int argc, char **argv)
{
#ifdef USE_MULTI_CLIENT
	/*
	std::thread thAccept(threadFunc);
	*/
	//HANDLE thAccept = CreateThread (0,0,(LPTHREAD_START_ROUTINE)threadFunc,0,0,0);
#endif
	WORD wVersionRequested = MAKEWORD(1,1);
	WSADATA wsaData;
	int nRet;
	short nPort;

	//
	// Check for port argument
	//
#ifndef USE_MY_CODE
	if (argc != 2)
	{
		fprintf(stderr,"\nSyntax: server PortNumber\n");
		return;
	}

	nPort = atoi(argv[1]);
#endif
	//
	// Initialize WinSock and check version
	//
	nRet = WSAStartup(wVersionRequested, &wsaData);
	if (wsaData.wVersion != wVersionRequested)
	{	
		fprintf(stderr,"\n Wrong version\n");
		return;
	}


	//
	// Do the stuff a stream server does
	//
#ifndef USE_MY_CODE
	StreamServer(nPort);
#else
	//////////////////////////////////////////////////////////////////////////

	const int INIT = -1;
	const int STATE_LISTEN = 0;
	const int STATE_CONNECTING = 1;
	const int STATE_EXIT = 2;
	int serverState = INIT;

	//
	// Create a TCP/IP stream socket to "listen" with
	//
	listenSocket = socket(AF_INET,			// Address family
		SOCK_STREAM,		// Socket type
		IPPROTO_TCP);		// Protocol

	if(listenSocket == INVALID_SOCKET)
	{
		serverState = INIT;
		printf("Can't create socket!!!!!");
		return;
	}
	serverState = STATE_LISTEN;

	//
	// Fill in the address structure
	//
	SOCKADDR_IN saServer;		
	nPort = 1000;
	saServer.sin_family = AF_INET;
	saServer.sin_addr.s_addr = INADDR_ANY;	// Let WinSock supply address
	saServer.sin_port = htons(nPort);		// Use port from command line
	
	//
	// bind the name to the socket
	//
	//int nRet;

	nRet = bind(listenSocket,	// Socket 
		(LPSOCKADDR)&saServer,	// Our address
		sizeof(struct sockaddr));// Size of address structure
	if (nRet == SOCKET_ERROR)
	{
		printf("Can't bind listenSocket!!!!");
		closesocket(listenSocket);
		return;
	}

	// Open listen port
	int nLen;
	nLen = sizeof(SOCKADDR);
	char szBuf[256];

	nRet = gethostname(szBuf, sizeof(szBuf));
	if (nRet == SOCKET_ERROR)
	{
		//PRINTERROR("gethostname()");
		closesocket(listenSocket);
		return;
	}

	//
	// Show the server name and port number
	//
	printf("\nServer named %s waiting on port %d\n",
		szBuf, nPort);

	//
	// Set the socket to listen
	//

	printf("\nlisten()");
	nRet = listen(listenSocket,	// Bound socket
		SOMAXCONN);	// Number of connection request queue
	if (nRet == SOCKET_ERROR)
	{
		//PRINTERROR("listen()");
		closesocket(listenSocket);
		return;
	}

	//
	// Wait for an incoming request
	//
	SOCKET	remoteSocket;
#ifdef USE_MULTI_CLIENT
	/*SOCKET clients[nMaxClients];*/
#endif

	int result = 0;
#ifdef USE_MULTI_CLIENT
	/*thAccept.join();*/
	HANDLE thAccept = CreateThread (0,0,(LPTHREAD_START_ROUTINE)threadFunc,0,0,0);
	bool isRunning = true;
	while(isRunning)
	{
		int focusedClientID = -1;
		if(nClientCounter > 0)
		{
			// Exists client accepted
			
			for(int i=0; i<nClientCounter; i++)
			{
				nRet = INVALID_SOCKET;
				/*
				int k = read(clients[i], szBuf, 255);
				printf("AAAAA: %d",k);
				*/
				printf("\nlistening from %d",i);
				nRet = recv(clients[i],					// Connected client
					szBuf,							// Receive buffer
					sizeof(szBuf),					// Length of buffer
					0);
				printf("\n333333333333333333");
				if (nRet == INVALID_SOCKET)
				{
					printf("\nClient %d disconnected!", i);
					removeSocket(i);
					if(nClientCounter == 0)
					{
						printf("\nExit!!!");
						closesocket(listenSocket);
						return;
					}
					/*
					closesocket(listenSocket);
					closesocket(remoteSocket);
					*/
				}
				else if(nRet > 0)
				{
					focusedClientID = i;
				}
			}
			if(focusedClientID >= 0)
			{
				szBuf[nRet]=0;
				printf("\nData received from client %d: %s", focusedClientID, szBuf);
				if(strcmp(szBuf,"exit") == 0)
				{
					printf("\nClient %d exit!", focusedClientID);
				}
				result = Caculate(szBuf);
				sprintf(szBuf, "Result: %d", result);
				//strcpy(szBuf, "Result: ");
				nRet = send(clients[focusedClientID],				// Connected socket
					szBuf,						// Data buffer
					strlen(szBuf),				// Lenght of data
					0);							// Flags
			}
		}
	}
	
#else
	serverState = STATE_CONNECTING;

	printf("\nBlocking at accept()");
	remoteSocket = accept(listenSocket,  // Listening socket
		NULL,	// Optional client address
		NULL);
	if (remoteSocket == INVALID_SOCKET)
	{
		printf("Can't remote socket");
		closesocket(listenSocket);
		return;
	}
	else
	{
		printf("\nAccept socket!!!");
		serverState = STATE_CONNECTING;
	}

	while(serverState == STATE_CONNECTING)
	{
		//
		// Receive data from the client
		//
		/*
		int error_socket_counter = 0;
		for(int i=0; i<nMaxClients; i++)
		{
			memset(szBuf, 0, sizeof(szBuf));
			nRet = recv(clients[i],
						szBuf,
						sizeof(szBuf),
						0);
			if(nRet == INVALID_SOCKET)
			{
				printf("\nClient %d ERROR!!!",i);
				closesocket(clients[i]);
				error_socket_counter++;
			}
			else if(nRet > 0)
			{
				szBuf[nRet]=0;
				printf("\nRecived from %d: %s",i,  szBuf);
				if(strcmp(szBuf,"exit") == 0)
				{
					serverState = STATE_EXIT;
				}
			}
		}
		if(error_socket_counter >= nMaxClients)
		{
			printf("\nEEEEEEEEEEEEEEEEEEEEEEEEEEEEE");
			closesocket(listenSocket);
			return;
		}
		*/
		
		nRet = recv(remoteSocket,					// Connected client
			szBuf,							// Receive buffer
			sizeof(szBuf),					// Length of buffer
			0);								// Flag
		
		if (nRet == INVALID_SOCKET)
		{
			OutputDebugString("ERROR");
			char s[256];
			sprintf(s, "%d", nRet);
			OutputDebugString(s);

			closesocket(listenSocket);
			closesocket(remoteSocket);
			serverState = STATE_EXIT;
			return;
			//OutputDebugString(
		}
		
		//
		// Display received data
		//
		
		if(nRet > 0)
		{
			szBuf[nRet]=0;
			printf("\nData received: %s", szBuf);
			if(strcmp(szBuf,"exit") == 0)
			{
				serverState = STATE_EXIT;
			}
		}
		
		
		//
		// Send data back to the client
		//
		result = Caculate(szBuf);
		sprintf(szBuf, "Result: %d", result);
		//strcpy(szBuf, "Result: ");
		nRet = send(remoteSocket,				// Connected socket
			szBuf,						// Data buffer
			strlen(szBuf),				// Lenght of data
			0);							// Flags
		
		//
		// Close BOTH sockets before exiting
		//
		
		//closesocket(remoteSocket);
		//closesocket(listenSocket);
		//return;
	}
	printf("\nServer exit\n");
	// closesocket(remoteSocket);
	closesocket(listenSocket);
#endif	//USE_MULTI_CLIENT
	//////////////////////////////////////////////////////////////////////////
#endif	//USE_MY_CODE
	

	//
	// Release WinSock
	//
	WSACleanup();
}


void StreamServer(short nPort)
{
	//
	// Create a TCP/IP stream socket to "listen" with
	//
	SOCKET	listenSocket;

	listenSocket = socket(AF_INET,			// Address family
		SOCK_STREAM,		// Socket type
		IPPROTO_TCP);		// Protocol
	if (listenSocket == INVALID_SOCKET)
	{
		/*PRINTERROR("socket()");*/
		return;
	}


	//
	// Fill in the address structure
	//
	SOCKADDR_IN saServer;		

	saServer.sin_family = AF_INET;
	saServer.sin_addr.s_addr = INADDR_ANY;	// Let WinSock supply address
	saServer.sin_port = htons(nPort);		// Use port from command line

	//
	// bind the name to the socket
	//
	int nRet;

	nRet = bind(listenSocket,	// Socket 
		(LPSOCKADDR)&saServer,	// Our address
		sizeof(struct sockaddr));// Size of address structure
	if (nRet == SOCKET_ERROR)
	{
		//PRINTERROR("bind()");
		closesocket(listenSocket);
		return;
	}

	//
	// This isn't normally done or required, but in this 
	// example we're printing out where the server is waiting
	// so that you can connect the example client.
	//
	int nLen;
	nLen = sizeof(SOCKADDR);
	char szBuf[256];

	nRet = gethostname(szBuf, sizeof(szBuf));
	if (nRet == SOCKET_ERROR)
	{
		//PRINTERROR("gethostname()");
		closesocket(listenSocket);
		return;
	}

	//
	// Show the server name and port number
	//
	printf("\nServer named %s waiting on port %d\n",
		szBuf, nPort);

	//
	// Set the socket to listen
	//

	printf("\nlisten()");
	nRet = listen(listenSocket,	// Bound socket
		SOMAXCONN);	// Number of connection request queue
	if (nRet == SOCKET_ERROR)
	{
		//PRINTERROR("listen()");
		closesocket(listenSocket);
		return;
	}

	//
	// Wait for an incoming request
	//
	SOCKET	remoteSocket;

	printf("\nBlocking at accept()");
	remoteSocket = accept(listenSocket,  // Listening socket
		NULL,	// Optional client address
		NULL);
	if (remoteSocket == INVALID_SOCKET)
	{
		//PRINTERROR("accept()");
		closesocket(listenSocket);
		return;
	}

	//
	// We're connected to a client
	// New socket descriptor returned already
	// has clients address

	//
	// Receive data from the client
	//
	memset(szBuf, 0, sizeof(szBuf));
	nRet = recv(remoteSocket,					// Connected client
		szBuf,							// Receive buffer
		sizeof(szBuf),					// Length of buffer
		0);								// Flags
	if (nRet == INVALID_SOCKET)
	{
		//PRINTERROR("recv()");
		closesocket(listenSocket);
		closesocket(remoteSocket);
		return;
	}

	//
	// Display received data
	//
	szBuf[nRet]=0;
	printf("\nData received: %s", szBuf);

	//
	// Send data back to the client
	//
	strcpy(szBuf, "From the Server");
	nRet = send(remoteSocket,				// Connected socket
		szBuf,						// Data buffer
		strlen(szBuf),				// Lenght of data
		0);							// Flags

	//
	// Close BOTH sockets before exiting
	//
	closesocket(remoteSocket);
	closesocket(listenSocket);
	return;
}

int Caculate(char* s)
{
	int result = 0;
	int n = strlen(s);
	int a,b;
	a = b = 0;
	int _operator = 0;
	bool isSecondVariable = false;
	for(int i=0;i<n;i++)
	{
		switch(s[i])
		{
			case '+':
				_operator = 1;
				isSecondVariable = true;
				break;
			case '-':
				_operator = 2;
				isSecondVariable = true;
				break;
			case '*':
				_operator = 3;
				isSecondVariable = true;
				break;
			case ':':
				_operator = 4;
				isSecondVariable = true;
				break;
			default:
				if(isSecondVariable)
				{
					b = 10*b + (s[i]-'0');
				}
				else
				{
					a = 10*a + (s[i]-'0');
				}
				break;
		}
	}
	switch(_operator)
	{
		case 1: //+
			result = a + b;
			break;
		case 2: //-
			result = a - b;
			break;
		case 3: //*
			result = a * b;
			break;
		case 4: //:
			result = a / b;
			break;
		default:
			printf("\nNon supported operator!!!!");
			break;
	}
	return result;
}